package nsga.population;

import java.util.ArrayList;
import java.util.List;

import GA.population.GAPopu;
import abstractGA.chrom.Chrom;
import abstractGA.popu.Population;

public class NSGAPopu extends GAPopu {
	protected PopuHelper popuHelper = null;
	public NSGAPopu() {
		super();
		popuHelper = new PopuHelper();
	}
	
	/**
	 * 交配选择
	 * @param chroms:染色体集合 
	 * @param 返回：选中染色体下标的数组
	 */
	@Override
	public int[] mutingChoose(List<Chrom> chroms) {
		int size = chroms.size();
		int[] idxs = new int[size];
		ArrayList<ArrayList<Integer>> idxss = popuHelper.nondominatedSort(chroms);
		for (int i = 0; i < size; i++) {
			int idx1 = random.nextInt(size);
			int idx2 = random.nextInt(size);
			if (idx1 == idx2) {
				idxs[i] = idx1;
			} else {
				int rank1 = popuHelper.getRank(idx1, idxss);
				int rank2 = popuHelper.getRank(idx2, idxss);
				if (rank1 < rank2) {
					idxs[i] = idx1;
				}
				if (rank1 == rank2) {
					ArrayList<Integer> frontIdxs = idxss.get(rank1);
					int posIdx1 = frontIdxs.indexOf(idx1);
					int posIdx2 = frontIdxs.indexOf(idx2);
					List<Float> distances = popuHelper.getCrowdDistances(chroms, frontIdxs);

					float dist1 = distances.get(posIdx1).floatValue();
					float dist2 = distances.get(posIdx2).floatValue();

					if (Float.compare(dist1, dist2) > 0) {
						idxs[i] = idx1;
					} else {
						idxs[i] = idx2;
					}
				}
				if (rank1 > rank2) {
					idxs[i] = idx2;
				}
			}
		}
		return idxs;
	}
	
	@Override
	/**
	 * 环境选择
	 * @param tempPopu：临时种群
	 * @return：环境选择后的种群
	 */
	public Population envSelect(Population tempPopu) {
		Population nxtPopu = copy();
		int popuSize = chroms.size();
		int tempPopuSize=tempPopu.getChroms().size();
		if (popuSize <= 0 || popuSize != tempPopuSize) {
			return nxtPopu;
		}	
		nxtPopu.add(tempPopu.getChroms());
		ArrayList<ArrayList<Integer>> idxss = popuHelper.nondominatedSort(nxtPopu
				.getChroms());
		ArrayList<Chrom> selChroms = new ArrayList<Chrom>();
		int i = 0;
		ArrayList<Integer> frontIdxs = idxss.get(i);
		int frontSize = frontIdxs.size();
		int selSize = 0;
		while (selSize + frontSize <= popuSize) {
			for (Integer frontIdx : frontIdxs) {
				selChroms.add(nxtPopu.getChroms().get(frontIdx).copy());
			}
			selSize = selChroms.size();
			i += 1;
			if (i < idxss.size()) {
				frontIdxs = idxss.get(i);
				frontSize = frontIdxs.size();
			} else {
				break;
			}
		}
		selSize = selChroms.size();
		if (selSize < popuSize && selSize + frontSize > popuSize) {
			List<Float> dists = popuHelper.getCrowdDistances(nxtPopu.getChroms(),
					frontIdxs);
			ArrayList<Integer> sortedIdxs = popuHelper.publeSort(dists, frontIdxs);
			int len = popuSize - selSize;
			for (int k = 0; k < len; k++) {
				int selIdx = sortedIdxs.get(k);
				selChroms.add(nxtPopu.getChroms().get(selIdx));
			}

		}
		nxtPopu.getChroms().clear();
		nxtPopu.setChroms(selChroms);
		return nxtPopu;
	}


	@Override
	public void crossover(int crossoverNum) {
		// 种群大小
		int popSize = chroms.size();
		// 产生交叉的位置
		int chromLen = parameter.getChromLen();
		// 获取交叉概率
		float crossProb = parameter.getCrossProb();
		boolean isCrossed = false;
		// 随机对种群的两个个体进交叉操作
		for (int i = 0; i < popSize && popSize >= 2; i++) {
			// 随机判断第i个体是否参与交叉
			float draw = random.nextFloat();
			// 第i个体参与交叉
			if (Float.compare(draw,crossProb)<0) {
				Chrom srcChrom = chroms.get(i).copy();
				// 随机产生另一个交叉个体
				int otherIdx = random.nextInt(popSize);
				// 避免自身交叉
				while (otherIdx == i) {
					otherIdx = random.nextInt(popSize);
				}
				Chrom desChrom = chroms.get(otherIdx).copy();
				int crossPos = random.nextInt(chromLen);
				while (crossPos == 0) {// 防止第0位交叉，种群不变化
					crossPos = random.nextInt(chromLen);
				}
				List<List<StringBuffer>> tempChroms = doCrossover(srcChrom,
						desChrom, crossPos);
				//新编码的合法性检查和修复
				List<StringBuffer> srcCodes = new ArrayList<StringBuffer>();
				srcCodes = tempChroms.get(0);
				if(!srcChrom.getAlgOper().isLegalCodes(srcCodes)){
					srcCodes = srcChrom.getAlgOper().repairCodes(srcCodes);
					srcChrom.setCodes(srcCodes);
				}
				//新编码的合法性检查和修复
				List<StringBuffer> desCodes = new ArrayList<StringBuffer>();
				desCodes = tempChroms.get(1);
				if(!desChrom.getAlgOper().isLegalCodes(desCodes)){
					desCodes = desChrom.getAlgOper().repairCodes(desCodes);
					desChrom.setCodes(desCodes);
				}
						
				chroms.set(i, srcChrom);
				chroms.set(otherIdx, desChrom);
				isCrossed = true;
			}
		}
		if (isCrossed) {
			bestChroms.clear();
		}
	}
	
	@Override
	/**
	 * 获取pareto最优染色体集
	 */
	public List<Chrom> getBestChroms() {	
		if (bestChroms.size() == 0) {
			if (chroms.size() > 0) {
				// 非支配排序
				ArrayList<ArrayList<Integer>> idxss = popuHelper.nondominatedSort(chroms);
				ArrayList<Integer> idxs = idxss.get(0);
				for (Integer idx : idxs) {
					bestChroms.add(chroms.get(idx).copy());				
				}
			}
		}		
		return bestChroms;
	}
	
	@Override
	//种群复制
	public Population copy() {
		Population newPopu = new NSGAPopu();
		List<Chrom> newBestChroms = new ArrayList<Chrom>();
		for (Chrom bestChrom : bestChroms) {
			newBestChroms.add(bestChrom.copy());
		}
		newPopu.setBestChroms(newBestChroms);
		// 复制种群中的染色体
		for (int i = 0; i < chroms.size(); i++) {
			Chrom tmpChrom = chroms.get(i);
			newPopu.getChroms().add(tmpChrom.copy());
		}
		newPopu.setRandom(random);

		newPopu.setParameter(parameter);
		return newPopu;
	}
	
}
